import dayjs from 'dayjs'
import type { TreeNode } from '@/types/common'

/**
 * 格式化日期
 * @param date 日期
 * @param format 格式
 */
export function formatDate(date: string | Date | null, format = 'YYYY-MM-DD HH:mm:ss'): string {
  if (!date) return ''
  return dayjs(date).format(format)
}

/**
 * 格式化文件大小
 * @param size 文件大小（字节）
 */
export function formatFileSize(size: number): string {
  if (size < 1024) {
    return size + ' B'
  } else if (size < 1024 * 1024) {
    return (size / 1024).toFixed(2) + ' KB'
  } else if (size < 1024 * 1024 * 1024) {
    return (size / (1024 * 1024)).toFixed(2) + ' MB'
  } else {
    return (size / (1024 * 1024 * 1024)).toFixed(2) + ' GB'
  }
}

/**
 * 防抖函数
 * @param fn 需要防抖的函数
 * @param delay 延迟时间
 */
export function debounce<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void {
  let timer: NodeJS.Timeout | null = null
  return function(this: any, ...args: Parameters<T>) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

/**
 * 节流函数
 * @param fn 需要节流的函数
 * @param delay 延迟时间
 */
export function throttle<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void {
  let last = 0
  return function(this: any, ...args: Parameters<T>) {
    const now = Date.now()
    if (now - last >= delay) {
      fn.apply(this, args)
      last = now
    }
  }
}

/**
 * 深拷贝
 * @param obj 需要深拷贝的对象
 */
export function deepClone<T>(obj: T): T {
  if (obj === null || typeof obj !== 'object') {
    return obj
  }

  if (obj instanceof Date) {
    return new Date(obj.getTime()) as any
  }

  if (obj instanceof Array) {
    return obj.map(item => deepClone(item)) as any
  }

  if (obj instanceof Object) {
    const copy = {} as any
    Object.keys(obj).forEach(key => {
      copy[key] = deepClone((obj as any)[key])
    })
    return copy
  }

  return obj
}

/**
 * 将列表数据转换为树形结构
 * @param list 列表数据
 * @param parentId 父节点ID
 * @param options 配置项
 */
export function listToTree(
  list: any[],
  parentId: number | string | null = null,
  options = { idKey: 'id', parentKey: 'parentId', childrenKey: 'children' }
): TreeNode[] {
  const tree: TreeNode[] = []
  const { idKey, parentKey, childrenKey } = options

  list.forEach(item => {
    if (item[parentKey] === parentId) {
      const node: TreeNode = {
        id: item[idKey],
        label: item.label || item.name || item.title,
        ...item
      }
      const children = listToTree(list, item[idKey], options)
      if (children.length) {
        node[childrenKey] = children
      }
      tree.push(node)
    }
  })

  return tree
}

/**
 * 获取树形数据中的所有叶子节点
 * @param tree 树形数据
 */
export function getTreeLeaves(tree: TreeNode[]): TreeNode[] {
  const leaves: TreeNode[] = []
  const stack = [...tree]

  while (stack.length) {
    const node = stack.pop()!
    if (!node.children || !node.children.length) {
      leaves.push(node)
    } else {
      stack.push(...node.children)
    }
  }

  return leaves
}

/**
 * 查找树形数据中的节点
 * @param tree 树形数据
 * @param predicate 判断函数
 */
export function findTreeNode(tree: TreeNode[], predicate: (node: TreeNode) => boolean): TreeNode | null {
  for (const node of tree) {
    if (predicate(node)) {
      return node
    }
    if (node.children) {
      const found = findTreeNode(node.children, predicate)
      if (found) {
        return found
      }
    }
  }
  return null
}

/**
 * 生成随机字符串
 * @param length 字符串长度
 */
export function randomString(length: number): string {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let result = ''
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return result
}

/**
 * 判断是否是外部链接
 * @param path 路径
 */
export function isExternal(path: string): boolean {
  return /^(https?:|mailto:|tel:)/.test(path)
}

/**
 * 获取URL参数
 * @param url URL字符串
 */
export function getUrlParams(url: string): Record<string, string> {
  const params: Record<string, string> = {}
  const searchParams = new URLSearchParams(url.split('?')[1])
  for (const [key, value] of searchParams) {
    params[key] = value
  }
  return params
}

/**
 * 将对象转换为URL参数字符串
 * @param params 参数对象
 */
export function objectToUrlParams(params: Record<string, any>): string {
  return Object.keys(params)
    .filter(key => params[key] !== undefined && params[key] !== null && params[key] !== '')
    .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
    .join('&')
} 